﻿using Newtonsoft.Json;
using XSot.BitBrowser.LocalApiClient.Model;

namespace XSot.BitBrowser.LocalApiClient
{
    /// <summary>
    /// 比特浏览器本地API客户端
    /// </summary>
    public interface IBitBrowserLocalApiClient
    {
        /// <summary>
        /// The base URI of the service.
        /// </summary>
        Uri BaseUri { get; }

        /// <summary>
        /// 
        /// </summary>
        string ApiKey { get; set; }

        /// <summary>
        /// 代理检测接口，可以用来查询代理信息，以及检测代理是否可用，注意如果 IP 需要在全局代理下使用，则要开全局
        /// </summary>
        /// <param name="ipCheckService">IP 检测渠道，默认 ip123in，可选 ip-api</param>
        /// <param name="host">代理主机</param>
        /// <param name="port">代理端口</param>
        /// <param name="proxyType">代理类型 http, socks5, ssh 选一</param>
        /// <param name="proxyUserName">代理用户名</param>
        /// <param name="proxyPassword">代理密码</param>
        /// <param name="checkExists">检测 IP 是否已使用，值为 1 或 0</param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserProxyCheckResult>> CheckAgentAsync(string ipCheckService = "ip123in", string? host = null, int? port = null, string? proxyType = null, string? proxyUserName = null, string? proxyPassword = null, int? checkExists = 0);

        /// <summary>
        /// 关闭所有的窗口
        /// </summary>
        /// <returns></returns>
        Task<HttpResult<string>> CloseAllBrowserAsync();


        /// <summary>
        /// 清空 cookie，7.0.2 及以上版本客户端支持
        /// <para>
        /// 无论窗口是否打开，此接口都能清理本地缓存中的 cookie，已同步到服务端的 cookie，用 saveSynced 字段控制，默认本地与云端一起清理掉
        /// </para>
        /// </summary>
        /// <param name="browserId"></param>
        /// <returns></returns>
        Task<HttpResult<string>> ClearBrowserCookie(string browserId);

        /// <summary>
        /// 保留扩展数据，删除窗口缓存
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<string>> ClearBrowserExceptExtensionsCacheAsync(string[] ids);

        /// <summary>
        /// 清理窗口缓存，注意，会清理掉所有的本地缓存文件，和服务端缓存文件
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<string>> ClearBrowserLocalAndServerCacheAsync(string[] ids);

        /// <summary>
        /// 重置浏览器关闭状态
        /// </summary>
        /// <param name="id">浏览器窗口 id</param>
        /// <returns></returns>
        Task<HttpResult<string>> CloseBrowserAsync(string id);

        /// <summary>
        /// 通过序号批量关闭窗口
        /// </summary>
        /// <param name="seqs"></param>
        /// <returns></returns>
        Task<HttpResult<string>> CloseBrowserBySeqListAsync(int[] seqs);

        /// <summary>
        /// 创建浏览器窗口，指定id则更新，否则创建
        /// </summary>
        /// <param name="profile"></param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserProfile>> CreateOrUpdateBroswerAsync(BitBrowserProfile profile);

        /// <summary>
        /// 删除浏览器窗口
        /// </summary>
        /// <param name="id">浏览器窗口 id</param>
        /// <returns></returns>
        Task<HttpResult<string>> DeleteBrowserAsync(string id);

        /// <summary>
        /// 批量删除窗口，一次最多 100 个
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<string>> DeleteBrowserByIdListAsync(string[] ids);

        /// <summary>
        /// 删除分组
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<HttpResult<string>> DeleteGroup(string id);

        /// <summary>
        /// 一键自适应排列窗口
        /// </summary>
        /// <param name="seqlist">窗口序号列表，如 [12, 14, 1889]， 不传则排列全部窗口</param>
        /// <returns></returns>
        Task<HttpResult<string>> FlexableWindowBoundsAsync(int[]? seqlist = null);

        /// <summary>
        /// 格式化给定 cookie，方便用户使用
        /// </summary>
        /// <param name="cookie">给定 cookie 数据，可能是数组，字符串等</param>
        /// <param name="hostname">cookie 的 domain 值，对于一些 cookie 中没有携带 domain 值的 cookie 数据，需要手动指定下 hostname 值，比如 .abc.com ，绝大部分 cookie 不需要专门指定</param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserCookie>> FormatCookie(string cookie, string hostname);

        /// <summary>
        /// 获取活着的给定窗口的 pids，会检查进程，减少进程退出，窗口状态没关闭的问题
        /// </summary>
        /// <param name="ids">窗口 id 集合，数组类型</param>
        /// <returns>
        /// "02d39dd4f9c54e40bc1ef51929d27235": 69902
        /// </returns>
        Task<HttpResult<IDictionary<string, int>>> GetAliveBrowserPidListAsync(int[] ids);


        /// <summary>
        /// 获取所有活着的已打开的窗口的进程 ID，会自动过滤掉已死掉的进程，无参数
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<IDictionary<string, int>>> GetAllBrowserPidListAsync();

        /// <summary>
        /// 获取浏览器窗口详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserProfile>> GetBrowserAsync(string id);

        /// <summary>
        /// 分页获取浏览器窗口列表，page 参数从 0 开始，0 是第一页的数据
        /// </summary>
        /// <param name="page">分页，从 0 开始</param>
        /// <param name="pageSize">分页数量，最大 100，超出 100 仍然返回 100 条，默认 10</param>
        /// <param name="groupId">分组 ID，传入时查询此分组下的窗口列表</param>
        /// <param name="name">窗口名称，模糊匹配</param>
        /// <param name="seq">序号，精确查询</param>
        /// <param name="minSeq">最小序号，范围查询，不可与 seq 同时使用</param>
        /// <param name="maxSeq">最大序号，范围查询，不可与 seq 同时使用</param>
        /// <param name="sort">排序参数，只允许两个值，desc 倒序，asc 正序</param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserPageList<BitBrowserProfile>>> GetBrowserListAsync(int? page = 0, int? pageSize = 10, string? groupId = null, string? name = null, int? seq = null, int? minSeq = null, int? maxSeq = null, string? sort = null);

        /// <summary>
        /// 获取所有已打开窗口的调试端口 remote-debugging-port
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<IDictionary<string, int>>> GetBrowserRDPListAsync(string[] ids);

        /// <summary>
        /// 查询分组列表接口,page 从 0 开始
        /// </summary>
        /// <param name="page">分页， 从 0 开始</param>
        /// <param name="pageSize">每页条数，最大 100 条，传入大于 100 的数字，也最多返回 100 条数据</param>
        /// <param name="all">是否获取权限范围内的所有分组</param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserPageList<BitBrowserGroupProfile>>> GetGroupList(int page = 0, int pageSize = 10, bool all = true);

        /// <summary>
        /// 获取已打开窗口的进程 pid 集合，也可以用来判断窗口是否已打开，支持批量查询
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        Task<HttpResult<IDictionary<string, int>>> GetBrowserPidListAsync(string[]? ids = null);

        /// <summary>
        /// 获取分组详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserGroupProfile>> GetGroupProfile(string id);

        /// <summary>
        /// 获取已打开窗口的实时 cookies，注意实时 cookie 可能一直在变，两次获取到的可能不一致
        /// </summary>
        /// <param name="browserId"></param>
        /// <returns></returns>
        Task<HttpResult<IList<BitBrowserCookie>>> GetOpendBrowserCookies(string browserId);

        /// <summary>
        /// 健康检查接口，无参数，可以用来测试 Local Server 是否连接成功
        /// </summary>
        /// <returns></returns>
        Task<HttpResult<string>> HealthAsync();

        /// <summary>
        /// 打开浏览器窗口
        /// </summary>
        /// <param name="id">浏览器窗口 id，创建完会返回 ID，或者通过 list 接口查询，或者界面上配置里点击【复制 ID】按钮复制，注意，ID 不是序号</param>
        /// <param name="queue">是否以队列方式打开，设置为 true 后，可有效防止多线程同时启动时导致的并发报错</param>
        /// <param name="args">浏览器启动参数，合法的 chromium 启动参数均支持，数组类型</param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserOpenResult>> OpenBrowserAsync(string id, bool queue = true, params string[] args);

        /// <summary>
        /// 随机指纹值，传入窗口 ID，随机一次指纹，返回指纹对象，注意，不是返回窗口对象，只返回指纹对象
        /// </summary>
        /// <param name="browserId"></param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserFingerPrint>> RandomBrowserFingerprintAsync(string browserId);

        /// <summary>
        /// 重置浏览器关闭状态
        /// </summary>
        /// <param name="id">浏览器窗口 id</param>
        /// <returns></returns>
        Task<HttpResult<string>> ResetBroswerClosingAsync(string id);

        /// <summary>
        /// 批量修改浏览器窗口分组
        /// </summary>
        /// <param name="groupId">要修改的分组编号</param>
        /// <param name="browserIds">要修改的窗口编号</param>
        /// <returns></returns>
        Task<HttpResult<string>> UpdateBrowserGroupAsync(string groupId, string[] browserIds);

        /// <summary>
        /// 批量修改窗口代理信息
        /// </summary>
        /// <param name="ids">浏览器窗口 ID 数组</param>
        /// <param name="ipCheckService">IP 查询渠道，默认 ip123in，选项 ip-api, luminati，luminati 为 Luminati 专用</param>
        /// <param name="proxyMethod">代理方式，2 自定义代理，3 提取 IP，默认 2</param>
        /// <param name="proxyType">代理类型，可选http, https, socks5, ssh 默认 noproxy</param>
        /// <param name="host">代理主机</param>
        /// <param name="port">代理端口</param>
        /// <param name="proxyUserName">代理用户名</param>
        /// <param name="proxyPassword">代理密码填</param>
        /// <param name="refreshProxyUrl">代理刷新 URL 填</param>
        /// <param name="dynamicIpUrl">提取 IP url</param>
        /// <param name="dynamicIpChannel">提取 IP 服务商 rola, ipidea, deoveip, cloudam, common 默认填 common 即可</param>
        /// <param name="isDynamicIpChangeIp">true，每次打开窗口都提取新 IP， false，上次的 IP 失效时才提取新 IP</param>
        /// <param name="isIpv6">是否是 IPv6，默认 false</param>
        /// <returns></returns>
        Task<HttpResult<string>> UpdateBrowserProxyAsync(string[] ids, string? ipCheckService = null, int? proxyMethod = null, string? proxyType = null, string? host = null, int? port = null, string? proxyUserName = null, string? proxyPassword = null, string? refreshProxyUrl = null, string? dynamicIpUrl = null, string? dynamicIpChannel = null, bool? isDynamicIpChangeIp = null, bool? isIpv6 = null);

        /// <summary>
        /// 批量修改窗口备注
        /// </summary>
        /// <param name="browserIds">窗口 ID 数组，只改一个窗口备注时，传入一个 ID 即可</param>
        /// <param name="remark">备注信息</param>
        /// <returns></returns>
        Task<HttpResult<string>> UpdateBrowserRemarkAsync(string[] browserIds, string? remark);

        /// <summary>
        /// 修改分组
        /// </summary>
        /// <param name="id"></param>
        /// <param name="groupName"></param>
        /// <param name="sortNum"></param>
        /// <returns></returns>
        Task<HttpResult<BitBrowserGroupProfile>> UpdateGroup(string id, string groupName, int sortNum = 0);

        /// <summary>
        /// 对已打开窗口设置实时
        /// </summary>
        /// <param name="browserId"></param>
        /// <param name="cookies"></param>
        /// <returns></returns>
        Task<HttpResult<string>> UpdateOpendBrowserCookie(string browserId, BitBrowserCookie[] cookies);

        /// <summary>
        /// 一键自适应排列窗口
        /// </summary>
        /// <param name="seqlist">窗口序号列表，如 [12, 14, 1889]， 不传则排列全部窗口</param>
        /// <returns></returns>
        Task<HttpResult<string>> WindowBoundsAsync(string type = "box", int? startX = 0, int? startY = 0, int? width = 500, int? height = 200, int col = 3, int? spaceX = 0, int? spaceY = 0, int? offsetX = 0, int? offsetY = 0, string? orderBy = "asc", string[]? ids = null, int[]? seqlist = null, int? screenId = null);
    }
}